cmake_minimum_required(VERSION 3.5)

# 添加项目并且开启了对 C, C++ 和 汇编语言的支持
project(stm32_template LANGUAGES C CXX ASM)

# 目标系统类型必须设置
# Linux 系统设备设为 Linux 类型
#set(CMAKE_SYSTEM_NAME Linux)
# 非 Linux 系统嵌入式设备设为通用类型
set(CMAKE_SYSTEM_NAME Generic)

# 如果出现 cmake is not able to compile a simple test program 这样的错误信息则尝试
# 跳过 CMakeTestCCompiler 的检测，交叉编译工具可能没法通过这个检测,有以下三种方式跳过
# 1. 提前标记检测通过
#set(CMAKE_C_COMPILER_WORKS TRUE)
#set(CMAKE_CXX_COMPILER_WORKS TRUE)
# 2. 强制使用指定编译器，不进行检测
# specify the cross compiler
#include(CMakeForceCompiler)
#cmake_force_c_compiler(arm-none-eabi-gcc GNU)
#cmake_force_cxx_compiler(arm-none-eabi-g++ GNU)
# 3. 设置编译类型为静态库类型
#set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")

# 工具链
# 使能汇编语言支持
#enable_language(ASM)
# 设置交叉编译器
set(TOOLCHAIN_PREFIX /usr/bin/arm-none-eabi-)
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++)
set(CMAKE_ASM_COMPILER ${TOOLCHAIN_PREFIX}gcc)
# 以下工具可以不设置
set(CMAKE_AR ${TOOLCHAIN_PREFIX}ar)
set(CMAKE_RANLIB ${TOOLCHAIN_PREFIX}ranlib)
#
set(OBJCOPY ${TOOLCHAIN_PREFIX}objcopy)
set(OBJDUMP ${TOOLCHAIN_PREFIX}objdump)
set(SIZE ${TOOLCHAIN_PREFIX}size)

# 设置 CMake 搜索文件的目录
#set(CMAKE_FIND_ROOT_PATH  /usr/arm-none-eabi)
# 在主机环境中寻找各种工具程序
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# 在目标环境中寻找头文件和库文件
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
#set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

# 如果出现 arm-none-eabi-gcc: error: unrecognized command line option '-rdynamic'
#set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
#set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")

# 必要文件
# 1. 启动文件
# 2. 链接脚本
# 配置启动文件和链接脚本的路径
set(CMSIS_ASM_DIR ${CMAKE_SOURCE_DIR}/src)
set(CMSIS_LD_DIR ${CMAKE_SOURCE_DIR}/src)
set(STARTUP_ASM ${CMSIS_ASM_DIR}/startup_stm32f103xe.s)
set(LINK_SCRIPT ${CMSIS_LD_DIR}/STM32F103XE_FLASH.ld)

# 配置编译参数
# Common flags
set(OPT_FLAGS "-Os -ffunction-sections -fdata-sections -fno-common -fno-builtin -ffreestanding")
set(C_STD_FLAGS "-std=c99")
set(CXX_STD_FLAGS "-std=c++11")
set(W_FLAGS "-Wall -Wundef")
# FPU flags
set(FPU_FLAGS "-mfloat-abi=soft")
# Device flags
set(MCU_FLAGS "-march=armv7-m -mcpu=cortex-m3 -mthumb ${FPU_FLAGS} --specs=nosys.specs --specs=nano.specs")
# Other flags
set(OTHER_FLAGS "-DVERBOSE=1")
# Set compile flags
#set(CMAKE_C_STANDARD 99)
#set(CMAKE_CXX_STANDARD 11)
set(CMAKE_C_FLAGS "${OPT_FLAGS} ${C_STD_FLAGS} ${W_FLAGS} ${MCU_FLAGS} ${OTHER_FLAGS}")
set(CMAKE_CXX_FLAGS "${OPT_FLAGS} ${CXX_STD_FLAGS} ${W_FLAGS} ${MCU_FLAGS} ${OTHER_FLAGS}")

# Link script flags
set(LD_FLAGS "-T${LINK_SCRIPT}")
#set(LD_FLAGS "-nostartfiles -nostdlib -T${LINK_SCRIPT}")
# Linker flags
set(CMAKE_EXE_LINKER_FLAGS "-Wl,-gc-sections,--print-memory-usage,--print-gc-sections ${LD_FLAGS}")

# 调试用
#message(STATUS "### toolchain c " ${CMAKE_C_COMPILER})
#message(STATUS "### toolchain c++ " ${CMAKE_CXX_COMPILER})

#message(STATUS "### link script " ${LINK_SCRIPT})
#message(STATUS "### startup " ${STARTUP_ASM})

# 添加全局宏
add_definitions(-DSTM32F103xE)

# 配置头文件路径
include_directories(
    Drivers/CMSIS/Include
    Drivers/CMSIS/Device/ST/STM32F1xx/Include
    Drivers/STM32F1xx_HAL_Driver/Inc
    src
)

# 添加源文件
aux_source_directory(src PROJ_SRCS)
aux_source_directory(Drivers/STM32F1xx_HAL_Driver/Src HAL_SRCS)

#add_subdirectory(dir)
#add_library($(libname) STATIC source)
#target_link_libraries(${PROJECT_NAME}.elf $(libname))

# 添加构建目标
add_executable(${PROJECT_NAME}.elf ${PROJ_SRCS} ${STARTUP_ASM} ${HAL_SRCS})


add_custom_target(File_info ALL
    COMMAND echo "==================== File size info ===================="
    COMMAND ${SIZE} -t ${PROJECT_NAME}.elf
    COMMAND echo "========================================================"
    DEPENDS ${PROJECT_NAME}.elf
    COMMENT "Echo file size info."
)

add_custom_target(${PROJECT_NAME}.bin ALL
    COMMAND ${OBJCOPY} -O binary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin
    DEPENDS ${PROJECT_NAME}.elf
    COMMENT "Build ${PROJECT_NAME}.bin ..."
)

add_custom_target(${PROJECT_NAME}.hex ALL
    COMMAND ${OBJCOPY} -O ihex ${PROJECT_NAME}.elf ${PROJECT_NAME}.hex
    DEPENDS ${PROJECT_NAME}.elf
    COMMENT "Build ${PROJECT_NAME}.hex ..."
)
